package multithread;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import controller.main;

public class CalculMultiThread extends Thread implements Runnable{
	
	private double Result;
	private double Time;
	private double Sum;
	private int count=0;
	private final int CoreNb = Runtime.getRuntime().availableProcessors();

	final double blockingCoefficient = 0.9;
    final int poolSize = (int)(CoreNb / (1 - blockingCoefficient));
	
	public CalculMultiThread(final String CallPutFlag,final double stock,final double strike,final double mat,final double rate,final double b, final double v
			,final int nSteps, final int nSimulation) throws InterruptedException, ExecutionException
	{
		
		long start = System.currentTimeMillis();
		int z = 1;
		final List<Callable<Double>> call = new ArrayList<Callable<Double>>();
	    
		 for(int i=0;i<nSimulation;i++) 
		    {
	 			call.add(new Callable<Double>() 
		    	{
		    		 public Double call() throws Exception
		    		 {
		    			 return thread_2(CallPutFlag,stock,strike,mat,rate,b,v,nSteps,nSimulation);
		    		 }       
		    	});
		    }
		final ExecutorService executorPool = Executors.newFixedThreadPool(poolSize);
		List<Future<Double>> StocksValue = executorPool.invokeAll(call);
		
		for(Future<Double> OneStockValue : StocksValue)
		{
			this.Sum=this.Sum + Math.max(z*(OneStockValue.get()-stock),0);
		}
		this.setResutl(java.lang.Math.exp((-rate) * mat)*(this.Sum/nSimulation));		
		this.Time=System.currentTimeMillis()-start;
	}
	
	
	
	public double thread_2(String CallPutFlag,double stock,double St,double mat,double rate,double b, double v
			,Integer nSteps, Integer nSimulation) 
	{
		Random rand = new Random();
		double dt = mat / nSteps;
		double vSqrdt = v * Math.sqrt(dt);
		double Drift = (b - (v*v) / 2) * dt;
		this.count++;
		main.GUI.MultiProgressBar.setValue(this.count);
			
			for(int j=1;j<=nSteps;j++)
			{
				St= St * java.lang.Math.exp(Drift + vSqrdt * rand.nextGaussian());
			}
			return  St;
	}
	
	

	public double getResutl() {
		return Result;
	}

	private void setResutl(double resutl) {
		Result = resutl;
	}

	public double getTime() {
		return Time;
	}
}

